// OnStyle
//
// Copyright (c)  Daigo Tanaka
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
onStyle.events = function(main)
{
var private = {};
var self = this;
var mousex = 0;
var mousey = 0;
var onMouseDownx = 0;
var onMouseDowny = 0;
var orix = 0;
var oriy = 0;
var elex = 0;
var eley = 0;
var elew = 0;
var eleh = 0;
var algor = 0;
var eventRoot = null;
var mouseOffsetX = 0;
var mouseOffsetY = 0;
var prevContext;
var mode = -1; // 0:pos 1:width

this.getEventRoot = function()
{
  return eventRoot;
}

this.setEventRoot = function(root)
{
  eventRoot = root;
}

this.setMouseOffset = function(x, y)
{
  mouseOffsetX = x;
  mouseOffsetY = y;
}

this.selectAll = function(elementID)
{
  var common = main.getCommon();
  common.selectAll(elementID);
}

this.changeRoot = function()
{
  main.changeRoot();
}

this.updateElementPositionAndSize = function()
{
  var designer = main.getDesigner();
  designer.updateElementPositionAndSize();
}

this.pushDownElement = function()
{
  var designer = main.getDesigner();
  designer.pushDownElement();
}

this.updateHtml = function()
{
  var editor = main.getEditor();
  editor.updateHtml();
}

this.getHtml = function(excludeStyle)
{
  var output = main.getOutput();
  output.getHtml(excludeStyle);
}

this.getCss = function()
{
  var output = main.getOutput();
  output.getCss();
}

this.hideOutputArea = function()
{
  var output = main.getOutput();
  output.hideOutputArea();
}

this.getEventTarget = function(event)
{
  var common = main.getCommon();
  if (!event) return false;
  var target = null;

  if (event.srcElement){
    target = event.srcElement;
  }
  else if (event.target){
    target = event.target;
  }

  var direct = true;
  while (target != document){
    if (target.id == onStyle.DialogID && direct == false) break;
    if (this.isValidTarget(target)){
      return target;
    }
    direct = false;
    target = target.parentNode;
  }
  return null;
};

this.isValidTarget = function(target)
{
  var container = main.getRootContainer();
  if (!target) return false;
  if (target == container) return true;
  if (target.id == onStyle.DialogID) return true;

  for (var childIndex = 0; childIndex < container.childNodes.length; childIndex++){
    if (target.id != onStyle.HighlightID && container.childNodes[childIndex].nodeName == "DIV" && container.childNodes[childIndex].id != "" && container.childNodes[childIndex] == target){
      return true;
    }
  }
  return false;
};

this.addEvent = function(element, event, callbackFunction, useCapture)
{
  if (!element || !event) return;

  if (element.addEventListener){
    element.addEventListener(event, callbackFunction, useCapture);
  }
  else if (element.attachEvent){ // For IE8 and earlier
    switch (event){
      case "mouseup":
        element.onmouseup = callbackFunction;
        break;
      case "mousedown":
        element.onmousedown = callbackFunction;
        break;
      default:
        element.attachEvent("on"+event, callbackFunction);
    }
  }
};

this.removeEvent = function(element, event, callbackFunction, useCapture)
{
  if (!element || !event) return;

  if (element.removeEventListener){
    element.removeEventListener(event, callbackFunction, useCapture);
  }
  else if (element.detachEvent){ // For IE8 and earlier
    switch (event){
      case "mouseup":
        element.onmouseup = null;
        break;
      case "mousedown":
        element.onmousedown = null;
        break;
      default:
        element.detachEvent("on"+event, callbackFunction);
    }
  }
};
this.update = function(event)
{
  var elementExpert = main.getElementExpert();

  self.getMouseXY(event); // NS is passing (event), while IE is passing (null)

  var dragElement = elementExpert.getDragElement();
  var selectedElement = elementExpert.getSelectedElement();
  if (!dragElement || dragElement != selectedElement ) return;

  onStyle.PosX = document.getElementById('osPosX');
  onStyle.PosY = document.getElementById('osPosY');
  onStyle.Width = document.getElementById('osWidth');
  onStyle.Height = document.getElementById('osHeight');
  if (mode == 0){
    if (onStyle.PosX){
      onStyle.PosX.value = elex;
    }
    if (onStyle.PosY){
      onStyle.PosY.value = eley;
    }
  }
  if (mode == 1){
    if (onStyle.Width){
      onStyle.Width.value = elew;
    }
    if (onStyle.Height){
      onStyle.Height.value = eleh;
    }
  }
}

this.onMouseOver = function(event)
{
  var common = main.getCommon();
  var elementExpert = main.getElementExpert();

  var target = self.getEventTarget(event);
  if (!target) return;
  var context = common.findObjectWithID(target);

  //
  // Highlight the selection
  //
  if (!elementExpert.getDragElement() ){
    var highlight = document.getElementById(onStyle.HighlightID);
    var container = main.getRootContainer();
    if (!highlight && elementExpert.isEditable(context) && context != container){
      context.innerHTML += "<img id=\""+ onStyle.HighlightImageID + "\" src=\""+onStyle.BGImageUrl+"\" style=\"position:absolute; top:0px; left:0px; width:100%;\" />";
      context.innerHTML += "<div id=\""+ onStyle.HighlightID + "\" style=\"position:absolute; top:0px; left:0px; width:100%; height:100%; background-color: Pink; /* for IE */ filter:alpha(opacity=50); opacity: 0.5; \">&nbsp;</div>";
      highlightedObject = context;
    }
    if (elementExpert.isDraggable(context) || elementExpert.isEditable(context)){
      elementExpert.setElementInFocus(context);
    }
  }
}

this.onMouseOut = function(event)
{
  var common = main.getCommon();
  var elementExpert = main.getElementExpert();
  var editor = main.getEditor();

  var target = self.getEventTarget(event);
  if (!target) return;
  var context = common.findObjectWithID(target);

  //
  // Turn off the highlight
  //
  if (!elementExpert.getDragElement()){
    var highlight = document.getElementById(onStyle.HighlightID);
    if (highlight){
      highlight.parentNode.removeChild(highlight);
    }
    highlight = document.getElementById(onStyle.EditButtonID);
    if (highlight){
      highlight.parentNode.removeChild(highlight);
    }
    highlight = document.getElementById(onStyle.HighlightImageID);
    if (highlight){
      highlight.parentNode.removeChild(highlight);
      if (context.style.zIndex == elementExpert.getHighestZIndexForElement() ){
        context.style.zIndex -= 1;
      }
    }

    var selectedElement = elementExpert.getSelectedElement(); 
    if (elementExpert.isEditable(selectedElement)){
      editor.update(selectedElement);
    }

    highlightedObject = null;
    elementExpert.setElementInFocus(null);
  }
}

this.getMouseXY = function(event) // works on IE6,FF,Moz,Opera7
{ 
  if (!event) event = window.event; // works on IE, but not NS (we rely on NS passing us the event)

  if (event)
  { 
    if (event.pageX || event.pageY)
    { // this doesn't work on IE6!! (works on FF,Moz,Opera7)
      mousex = event.pageX;
      mousey = event.pageY;
      algor = '[event.pageX]';
      if (event.clientX || event.clientY) algor += ' [event.clientX] '
    }
    else if (event.clientX || event.clientY)
    { // works on IE6,FF,Moz,Opera7
      mousex = event.clientX + document.body.scrollLeft;
      mousey = event.clientY + document.body.scrollTop;
      algor = '[event.clientX]';
      if (event.pageX || event.pageY) algor += ' [event.pageX] '
    }  
  }
}


this.onMouseDown = function(event)
{
  var common = main.getCommon();
  var elementExpert = main.getElementExpert();
  var editor = main.getEditor();
  var elementInFocus = elementExpert.getElementInFocus();

  var context = self.getEventTarget(event);
  if (!context){
    if (elementInFocus != null){
      context = elementInFocus;
    }
    else{
      return;
    }
  }

  if (!context) return;

  if (elementExpert.isDraggable(context)){
    elementExpert.setDragElement(context);
    context.style.zIndex = elementExpert.getHighestZIndexForElement();
  }

  if (elementExpert.isEditable(context) ){
    elementExpert.selectElement(context);
    var selectedID = document.getElementById(onStyle.SelectedID);
    var selectedElement = elementExpert.getSelectedElement()
    selectedID.value = selectedElement.id;
    editor.update(selectedElement);

    onStyle.PosX = document.getElementById('osPosX');
    onStyle.PosX.value = parseInt(selectedElement.style.left);
    onStyle.PosY = document.getElementById('osPosY');
    onStyle.PosY.value = parseInt(selectedElement.style.top);
    document.getElementById('osWidth').value = parseInt(selectedElement.style.width);
    document.getElementById('osHeight').value = parseInt(selectedElement.style.height);
    if (elementExpert.getSelectedElement() == container){
      onStyle.PosX.disabled = true;
      onStyle.PosY.disabled = true;
    }
    else{
      onStyle.PosX.disabled = false;
      onStyle.PosY.disabled = false;
    }
  }

  if (!elementExpert.isDraggable(context)) return; // cannot drag the root container

  // Add mouse event for drag and drop
  var dialog = main.getDialog();
  self.removeEvent(dialog, "mousemove", self.update, false);
  self.addEvent(dialog, "mousemove", self.drag, false);
  self.addEvent(dialog, "mouseup", self.drop, false);

  self.removeEvent(eventRoot, "mousemove", self.update, false);
  self.addEvent(eventRoot, "mousemove", self.drag, false);
  self.addEvent(eventRoot, "mouseup", self.drop, false);

  // Detect two objects being clicked at the same time
  if (onMouseDownx == mousex && onMouseDowny == mousey && context.id != prevContext.id){
	context = prevContext;
	elementExpert.setDragElement(prevContext);
  }
  // Double clicked?
  else if (onMouseDownx == mousex && onMouseDowny == mousey){
    // do nothing
  }

  prevContext = context;
  onMouseDownx = mousex;
  onMouseDowny = mousey;

  dragElement = elementExpert.getDragElement();
  elex = orix = dragElement.offsetLeft;
  eley = oriy = dragElement.offsetTop;
  elew = oriw = dragElement.offsetWidth;
  eleh = orih = dragElement.offsetHeight;

  if (onMouseDownx - elex < elew * 0.5 + mouseOffsetX){
    mode = 0;
    common.setCursor("move");
  }
  else if (elex + elew - onMouseDownx < elew * 0.5 + mouseOffsetX){
    mode = 1;
    common.setCursor("se-resize");
  }
  else{
    mode = -1;
  }

  self.update(event);
}

this.drag = function(event) // parameter passing is important for NS family 
{
  var elementExpert = main.getElementExpert();
  var dragElement = elementExpert.getDragElement();

  if (dragElement)
  {
    elex = orix + (mousex - onMouseDownx);
    eley = oriy + (mousey - onMouseDowny);
    elew = oriw + (mousex - onMouseDownx);
    eleh = orih + (mousey - onMouseDowny);

    if (mode == 0){
      dragElement.style.position = "absolute";
      dragElement.style.left = (elex).toString(10) + 'px';
      dragElement.style.top  = (eley).toString(10) + 'px';
      dragElement.style.backgroundPosition = (20-elex).toString(10) + 'px '+ (20-eley).toString(10) + 'px';
    }
    else if (mode == 1 && dragElement == elementExpert.getSelectedElement() ){
      dragElement.style.width  = (elew).toString(10) + 'px';
      dragElement.style.height = (eleh).toString(10) + 'px';
    }

  }
  self.update(event);
  return false; // in IE this prevents cascading of events, thus text selection is disabled
}

this.drop = function(event)
{
  var common = main.getCommon();
  var dialog = main.getDialog();

  self.update(event);

  self.removeEvent(dialog, "mousemove", self.drag, false);
  self.addEvent(dialog, "mousemove", self.update, false);

  self.removeEvent(eventRoot, "mousemove", self.drag, false);
  self.addEvent(eventRoot, "mousemove", self.update, false);

  common.setCursor("default");
  mode = -1;

  var elementExpert = main.getElementExpert();
  elementExpert.setDragElement(null);

  if (orix != elex || oriy != eley || oriw != elew || orih != eleh){
//    saveLayout();
  }
};

// used to block cascading events
private.falsefunc = function()
{
  return false;
};

};


